#pragma once

#include "Utils/Comparer.h"

class Bollinger;

const double MORE_UPPER =	10000001.00;
const double UPPER =		10000000.00;
const double LOWER =		-10000000.00;
const double MORE_LOWER =	-10000001.00;

class Band
{
public:
	Band(double open,double offset,double stop);
	double GetOpen() const { return m_open; }
	double GetOffset() const { return m_offset; }
	double GetStop() const { return m_stop; }

	bool IsValid() const 
	{
		bool bearish = m_open < m_offset && m_open > m_stop;
		bool bullish = m_open > m_offset && m_open < m_stop;
		return bearish || bullish;
	}

	bool IsSameType(Band const& other) const
	{
		return m_openComparer == other.m_openComparer;
	}

	bool CanOpen(double openBalance, double stopBalance) const 
	{
		return CanOpen(openBalance,stopBalance,m_open);
	}

	bool IsLostOpenMarket(double openBalance, double stopBalance, double minPriceUnit) const
	{
		return !IsOpenMarket(openBalance,stopBalance,minPriceUnit);
	}
	bool IsOpenMarket(double openBalance, double stopBalance, double minPriceUnit) const
	{
		if (IsSameType(CreateBearish()))
		{
			return CanOpen(openBalance,stopBalance,m_open + minPriceUnit);
		}
		else
		{
			return CanOpen(openBalance,stopBalance,m_open - minPriceUnit);
		}
	}
	

	bool CanOffset(double offsetBalance) const
	{
		return m_offsetComparer(offsetBalance,m_offset);
	}

	bool CanStop(double stopBalance) const
	{
		return m_openComparer(stopBalance,m_stop);
	}

	void UpdateByBollinger(Bollinger const& bollinger);

	bool operator== (Band const& other) const
	{
		return m_open == other.m_open && m_offset == other.m_offset && m_stop == other.m_stop;
	}
	bool operator!= (Band const& other) const
	{
		return !operator==(other);
	}

	static Band CreateBearish()
	{
		return Band(LOWER,UPPER,MORE_LOWER);
	}
	static Band CreateBullish()
	{
		return Band(UPPER,LOWER,MORE_UPPER);
	}
private:

	bool CanOpen(double openBalance, double stopBalance, double open) const
	{
		return m_openStopComparer(openBalance,stopBalance) &&
			m_openComparer(openBalance, open) &&
			m_openStopComparer(stopBalance,m_stop);
	}

	double m_open;
	double m_offset;
	double m_stop;

	Comparer::CompareFunction m_openComparer;
	Comparer::CompareFunction m_offsetComparer;
	Comparer::CompareFunction m_openStopComparer;
};
